package cn.tedu.eshihui.service.impl;

import cn.tedu.eshihui.ex.ServiceException;
import cn.tedu.eshihui.mapper.AdminMapper;
import cn.tedu.eshihui.mapper.AdminRoleMapper;
import cn.tedu.eshihui.pojo.dto.AdminAddNewDTO;
import cn.tedu.eshihui.pojo.dto.AdminLoginDTO;
import cn.tedu.eshihui.pojo.dto.AdminUpdateDTO;
import cn.tedu.eshihui.pojo.entity.Admin;
import cn.tedu.eshihui.pojo.entity.AdminRole;
import cn.tedu.eshihui.pojo.vo.AdminListItemVO;
import cn.tedu.eshihui.pojo.vo.AdminStandardVO;
import cn.tedu.eshihui.security.AdminDetails;
import cn.tedu.eshihui.service.IAdminService;
import cn.tedu.eshihui.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.*;

@Slf4j
@Service
public class AdminServiceImpl implements IAdminService {



    @Autowired
    private AdminMapper adminMapper;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private AdminRoleMapper adminRoleMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;


    @Value("${csmall.jwt.secret-key}")
    private String secretKey;

    @Value(("${csmall.jwt.duration-minute}"))
    private long durationInMinute;

    @Override
    public String login(AdminLoginDTO adminLoginDTO) {
        Authentication authentication = new
                UsernamePasswordAuthenticationToken(
                adminLoginDTO.getUsername(), adminLoginDTO.getPassword());

        Authentication authenticationResult = authenticationManager.authenticate(authentication);
        log.debug("认证通过，认证结果：{}", authenticationResult);
        log.debug("认证通过，认证结果中的当事人：{}", authenticationResult.getPrincipal());
        Date date = new Date(System.currentTimeMillis() + durationInMinute * 60 * 1000);
        AdminDetails principal = (AdminDetails) authenticationResult.getPrincipal();
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", principal.getId());
        claims.put("username", principal.getUsername());

        Collection<GrantedAuthority> authorities = principal.getAuthorities();
        String authoritiesJsonString = JSON.toJSONString(authorities);
        claims.put("authoritiesJsonString", authoritiesJsonString);

        String jwt = Jwts.builder().
                setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")
                // Payload
                .setClaims(claims)
                // Signature
                .setExpiration(date)
                .signWith(SignatureAlgorithm.HS256, secretKey)
                // 完成
                .compact();

        log.debug("返回JWT数据，JWT：{}", jwt);
        return jwt;

    }

    @Override
    public void addNew(AdminAddNewDTO adminAddNewDTO) {
        log.debug("开始处理【添加管理员】的业务，参数：{}", adminAddNewDTO);
//        检测角色ID的数组中是否包含1号角色
        Long[]roleIds=adminAddNewDTO.getRoleIds();
        for (int i = 0; i <roleIds.length ; i++) {
            if (roleIds[i]== 1) {
                String message = "添加失败，非法访问";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
            }

        }
        {
            // 从参数对象中取出用户名
            String adminName = adminAddNewDTO.getUsername();
            // 调用adminMapper.countByUsername()执行统计
            int count = adminMapper.countByName(adminName);
            // 判断统计结果是否大于0
            if (count > 0) {
                // 是：抛出异常（ERR_CONFLICT）
                String message = "添加管理员失败，尝试使用的用户名已经被占用！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
            }
        }

        {
            // 从参数对象中取出手机号码
            String phone = adminAddNewDTO.getPhone();
            // 调用adminMapper.countByPhone()执行统计
            int count = adminMapper.countByPhone(phone);
            // 判断统计结果是否大于0
            if (count > 0) {
                // 是：抛出异常（ERR_CONFLICT）
                String message = "添加管理员失败，尝试使用的手机号码已经被占用！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
            }
        }

        {
            // 从参数对象中取出电子邮箱
            String email = adminAddNewDTO.getEmail();
            // 调用adminMapper.countByEmail()执行统计
            int count = adminMapper.countByEmail(email);
            // 判断统计结果是否大于0
            if (count > 0) {
                // 是：抛出异常（ERR_CONFLICT）
                String message = "添加管理员失败，尝试使用的电子邮箱已经被占用！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
            }
        }

        // 创建Admin对象
        Admin admin = new Admin();
        // 复制参数DTO对象中的属性到实体对象中
        BeanUtils.copyProperties(adminAddNewDTO, admin);
        // 设置初始登录次数
        admin.setLoginCount(0);
        // 处理密码加密
        String rowPassword = admin.getPassword();
        String encodedPassword = passwordEncoder.encode(rowPassword);
        admin.setPassword(encodedPassword);

        // 调用adminMapper.insert()方法插入管理员数据
        int rows = adminMapper.insert(admin);
        if (rows != 1) {
            String message = "添加管理员失败，服务器忙，请稍后再尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }

        AdminRole[]adminRoles=new AdminRole[roleIds.length];
        for (int i=0;i<adminRoles.length;i++){
            AdminRole adminRole=new AdminRole();
            adminRole.setAdminId(admin.getId());
            adminRole.setRoleId(roleIds[i]);
            adminRoles[i]=adminRole;
        }
        rows=adminRoleMapper.insertBatch(adminRoles);
        if (rows != adminRoles.length) {
            String message = "添加管理员失败，服务器忙，请稍后再尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }

    }

    @Override
    public void deleteById(Long id) {
        if (id == 1) {
            String message = "未找到该管理员，删除失败";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        AdminStandardVO admin = adminMapper.getStandardById(id);
        if (admin == null) {
            String message = "未找到该管理员，删除失败";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        int rows = adminMapper.deleteById(id);
        if (rows != 1) {
            String message = "删除管理员失败，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        }
        // 执行删除--管理员与角色的关联表
        rows = adminRoleMapper.deleteByAdminId(id);
        if (rows < 1) {
            String message = "删除管理员失败，服务器忙，请稍后再尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        }

    }

    @Override
    public void updateInfoById(Long id, AdminUpdateDTO adminUpdateDTO) {
        if (id == 1) {
            String message = "修改管理员详情失败，尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        {
            AdminStandardVO admin = adminMapper.getStandardById(id);
            if (admin == null) {
                String message = "修改管理员详情失败，尝试访问的数据不存在！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
            }
        }
        {
            int count = adminMapper.countByNameAndNotId(id, adminUpdateDTO.getUsername());
            if (count > 1) {
                String message = "修改管理员信息失败，新的管理员名称已经被占用！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
            }
        }
        Admin admin = new Admin();
        BeanUtils.copyProperties(adminUpdateDTO, admin);
        admin.setId(id);
        int rows = adminMapper.update(admin);
        if (rows != 1) {
            String message = "修改管理员信息失败，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
    }

    @Override
    public void setEnable(Long id) {

        updateEnableById(id, 1);
    }

    @Override
    public void setDisable(Long id) {
        updateEnableById(id, 0);
    }

    @Override
    public List<AdminListItemVO> list() {
        List<AdminListItemVO> list = adminMapper.list();
        log.debug("返回查询结果，{}", list);

        Iterator<AdminListItemVO> iterator = list.iterator();
        while (iterator.hasNext()) {
            AdminListItemVO admin = iterator.next();
            if (admin.getId() == 1) {
                iterator.remove();
                break;
            }
        }
        return list;
    }


    private void updateEnableById(Long id, Integer enable) {
        String[] enableText = {"禁用", "启用"};
        {
            if (id == 1) {
                String message = enableText[enable] + "管理员失败，尝试访问数据不存在";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
            }

            AdminStandardVO adminVO = adminMapper.getStandardById(id);
            if (adminVO == null) {
                String message = enableText[enable] + "管理员失败，尝试访问数据不存在";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
            }

            if (adminVO.getEnable() == enable) {
                String message = enableText[enable] + "管理员失败，当前管理员已" + enableText[enable];
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
            }
            Admin admin = new Admin();
            admin.setId(id);
            admin.setEnable(enable);
            int rows = adminMapper.update(admin);
            if (rows != 1) {
                String message = enableText[enable] + "管理员失败，服务器忙，请稍后再次尝试！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_UPDATE, message);
            }
        }

    }
}